#include "hc_sr04.h"

/************************************************************************
*函数名：Ultrasound_IO_Init
*函数功能：超声波IO口初始化配置函数
*函数参数：无
*函数返回值：无
*函数说明：TIM5_CH1——PA0——复用功能AF2
*************************************************************************/
void Ultrasound_IO_Init(void)
{
	/*使能GPIOA、GPIOB时钟*/
	RCC->AHB1ENR |= (1<<0);//使能GPIOA时钟
	RCC->AHB1ENR |= (1<<1);//使能GPIOB时钟

	/*配置GPIO控制器*/
	//模式寄存器——复用功能模式 10，通用输出模式 01
	GPIOA->MODER &= ~	(3<<0*2);
	GPIOA->MODER |= 		(2<<0*2);
	GPIOB->MODER &= ~	(3<<0*2);
	GPIOB->MODER |= 		(1<<0*2);

	//输出类型寄存器——推挽 0
	GPIOA->OTYPER &= ~(1<<0);
	GPIOB->OTYPER &= ~(1<<5);

	//输出速度寄存器——低速 00
	GPIOA->OSPEEDR &= ~(3<<0*2);
	GPIOB->OSPEEDR &= ~(3<<5*2);

	//上拉/下拉寄存器——无上下拉 00
	GPIOA->PUPDR &= ~(3<<0*2);
	GPIOB->PUPDR &= ~(3<<5*2);

	//复用功能低位寄存器——AF2
	GPIOA->AFR[0] &= ~	(0xf<<0*4);
	GPIOA->AFR[0] |= 	(2<<0*4);
}


/************************************************************************
*函数名：Ultrasound_Init
*函数功能：超声波初始化配置函数
*函数参数：无
*函数返回值：无
*函数说明：1ms进一次中断
*************************************************************************/
void Ultrasound_Init(void)
{
	/*超声波IO口初始化配置*/
	Ultrasound_IO_Init();

	/*使能TIM5时钟*/
	RCC->APB1ENR |= (1<<3);

	/*配置TIM5时基单元*/
	TIM5->CNT = 0;//计数器清零
	TIM5->PSC = 84-1;//分频84
	TIM5->ARR = 1000-1;//重装载值1000（1ms更新一次）

	/*配置TIM5寄存器*/
	TIM5->CR1 |= (1<<7);//ARR寄存器进行缓冲
	TIM5->CR1 &= ~(1<<3);//计数器更新后不会停止，而是重新开始计数
	TIM5->CR1 &= ~(1<<2);//UEV源：上溢/下溢，UG位置1等
	TIM5->CR1 &= ~(1<<1);//使能更新事件

	/*软件更新（可选）*/
	TIM5->EGR |= (1<<0);//UG位置1，手动更新
	TIM5->SR &= ~(1<<0);//清零中断标志位

	/*CC1输入捕获配置*/
	TIM5->CCMR1 &= ~(0xff<<0*8);//清零0-7位
	TIM5->CCMR1 |= (1<<0*2);//定义CC1通道方向为输入，IC1→TI1
	TIM5->CCER |= (1<<3|1<<1);//捕获1输出极性：双边沿触发
	TIM5->CCER |= (1<<0);//使能输入捕获1

	/*开启TIM5中断*/
	//在DIER开启捕获1中断、更新中断
	TIM5->DIER |= (1<<1|1<<0);
	//设置中断优先级
	NVIC_SetPriority(TIM5_IRQn,NVIC_EncodePriority(7-2,2,3));//给TIM5设置优先级为(2,3)
	//使能中断源
	NVIC_EnableIRQ(TIM5_IRQn);

	/*打开计数器*/
	TIM5->CR1 |= (1<<0);
}


/***********************************************************************************
*函数名：Ultrasound_Measure
*函数功能：超声波测距函数
*函数参数：无
*函数返回值：u32，距离（cm）
*函数说明：
************************************************************************************/
void Ultrasound_Measure(void)
{
	GPIOB->ODR &= ~(1<<5);//PB5初始状态重置为低电平
	GPIOB->ODR |= (1<<5);//PB5开始输出高电平
	TIM6_delay_ms(1);
	GPIOB->ODR &= ~(1<<5);//PB5结束输出高电平
}



/************************************************************************
*函数名：TIM5_IRQHandler
*函数功能：TIM5中断服务函数
*函数参数：无
*函数返回值：无
*函数说明：
*************************************************************************/
//#define diff_count ((count_DOWN-count_UP)*1000+CCR1_DOWN-CCR1_UP)
//
//void TIM5_IRQHandler(void)
//{
//	static u32 count_UEV = 0;
//	static u32 count_UP = 0,count_DOWN = 0;
//	static u16 CCR1_UP = 0,CCR1_DOWN = 0;
//	if (TIM5->SR & (1<<0))//如果是更新中断
//	{
//		TIM5->SR &= ~(1<<0);//清零中断标志位
//		count_UEV++;
//	}
//	if (TIM5->SR & (1<<1))//如果是捕获/比较1中断
//	{
//		TIM5->CCR1;//读取CCR1，将SR的第1位清零
//
//		printf("TIM5 captured:");
//		if (GPIOA->IDR & (1<<0))//如果PA0输入高电平
//		{
//			printf("0 UP\n");
//			CCR1_UP = TIM5->CCR1;
//			count_UP = count_UEV;
//			printf("CNT:%d\n",TIM5->CCR1);
//			printf("count_UEV:%d\n",count_UEV);
//		}
//		else
//		{
//			printf("0 DOWN\n");
//			CCR1_DOWN = TIM5->CCR1;
//			count_DOWN = count_UEV;
//			printf("CNT:%d\n",TIM5->CCR1);
//			printf("count_UEV:%d\n",count_UEV);
//			printf("\n");
//			printf("diff count:%d\n",diff_count);
//			printf("diff time:%.4f ms\n",diff_count/1000.0);
//		}
//	}
//}
